#include "circ_buf.h"
#include <cstdio>

void circ_buf_init(circ_buf_t *circ_buf, uint8_t *buffer, unsigned int size)
{
    //  cortex_int_state_t state;
    //  state = cortex_int_get_and_disable();

    circ_buf->buf = buffer;
    circ_buf->size = size;
    circ_buf->head = 0;
    circ_buf->tail = 0;
    //   cortex_int_restore(state);
}

void circ_buf_push(circ_buf_t *circ_buf, uint8_t data)
{
    // cortex_int_state_t state;
    // state = cortex_int_get_and_disable();

    circ_buf->buf[circ_buf->tail] = data;
    circ_buf->tail += 1;
    if (circ_buf->tail >= circ_buf->size)
    {
        // util_assert(circ_buf->tail == circ_buf->size);
        circ_buf->tail = 0;
    }
}

unsigned char circ_buf_pop(circ_buf_t *circ_buf)
{
    unsigned char data;

    data = circ_buf->buf[circ_buf->head];
    circ_buf->head += 1;
    if (circ_buf->head >= circ_buf->size)
    {
        circ_buf->head = 0;
    }
    return data;
}

unsigned int circ_buf_count_used(circ_buf_t *circ_buf)
{
    unsigned int cnt;
    if (circ_buf->tail >= circ_buf->head)
    {
        cnt = circ_buf->tail - circ_buf->head;
    }
    else
    {
        cnt = circ_buf->tail + circ_buf->size - circ_buf->head;
    }

    //  cortex_int_restore(state);
    return cnt;
}

unsigned int circ_buf_count_free(circ_buf_t *circ_buf)
{
    unsigned int cnt;
    // cortex_int_state_t state;

    // state = cortex_int_get_and_disable();

    cnt = circ_buf->size - circ_buf_count_used(circ_buf) - 1;

    //  cortex_int_restore(state);
    return cnt;
}

unsigned int circ_buf_read(circ_buf_t *circ_buf, uint8_t *data, unsigned int size)
{
    unsigned int cnt;
    unsigned int i;

    cnt = circ_buf_count_used(circ_buf);
    cnt = MIN(size, cnt);
    for (i = 0; i < cnt; i++)
    {
        data[i] = circ_buf_pop(circ_buf);
    }

    return cnt;
}

unsigned int circ_buf_write(circ_buf_t *circ_buf, uint8_t *data, unsigned int size)
{
    unsigned int cnt;
    unsigned int i;

    cnt = circ_buf_count_free(circ_buf);
    cnt = MIN(size, cnt);
    for (i = 0; i < cnt; i++)
    {
        circ_buf_push(circ_buf, data[i]);
    }

    return cnt;
}
